package com;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import model.CoverTable;
import model.tagTable;


import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;


public class fly {

    public static void main(String[] args) {
        try {
            Configuration configuration = new Configuration(Configuration.getVersion());
            configuration.setDirectoryForTemplateLoading(new File("C:\\Users\\Administrator\\Desktop\\zhafurong\\test"));
            configuration.setDefaultEncoding("UTF-8");
            Template template = configuration.getTemplate("cover" + ".ftl");
            Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File("C:\\Users\\Administrator\\Desktop\\zhafurong\\test\\" + "cover.html")), StandardCharsets.UTF_8));
            HashMap<String, Object> map = new HashMap<>();
            map.put("a",0);
            map.put("b",1);
            template.process(map, writer);
            writer.close();
        } catch (IOException | TemplateException e) {
            e.printStackTrace();
        }
    }



    /*多次用到，所以写在这里*/
    private final static String sp = File.separator;

    /*内置比较器*/
    public static Comparator<String> c = (o1, o2) -> {
        String[] so1 = o1.split("_");
        String[] so2 = o2.split("_");
        if (Integer.parseInt(so1[0]) < Integer.parseInt(so2[0])) {
            return -1;
        }
        if (Integer.parseInt(so1[0]) > Integer.parseInt(so2[0])) {
            return 1;
        }
        if (Integer.parseInt(so1[0]) == Integer.parseInt(so2[0])) {
            if (Integer.parseInt(so1[1]) == Integer.parseInt(so2[1])) {
                return 0;
            }
            if (Integer.parseInt(so1[1]) < Integer.parseInt(so2[1])) {
                return -1;
            }
            if (Integer.parseInt(so1[1]) > Integer.parseInt(so2[1])) {
                return 1;
            }
        }
        return 0;
    };

    public static Comparator<String> c2 = (o1, o2) -> {
        int a1 = Integer.parseInt(o1.substring(1, 2));
        int a2 = Integer.parseInt(o1.substring(2, 3));
        int b1 = Integer.parseInt(o2.substring(1, 2));
        int b2 = Integer.parseInt(o2.substring(2, 3));
        if (a1<b1) {
            return -1;
        }
        if (a1>b1) {
            return 1;
        }
        if (a2==b2) {
            return 0;
        }
        if (a2<b2) {
            return -1;
        }
        if (a2>b2) {
            return 1;
        }
        return 0;
    };

    /*主路口*/
    public static void run(String packagePath){
        /*copy 基本的web文件css jss*/
        copyWebBaseNeed(packagePath);

        /*在web目录下创建res目录,只创建文件夹*/
        mkDirRes(parentDirectoryPath(packagePath));

        /*初始化不缺分析数据的数据表格,一共5个键值对，对应html的五个大模块*/
        HashMap<String, tagTable> completeData = initCompleteData();

        /*这是个重要的步骤，还要把所需的数据变成html到对应的位置*/
        HashMap<String, String> keyMap = dataToHtml.becomeHtml(packagePath);

        /*删减coverData*/
        completeData = insertCompleteData(completeData, keyMap);

        /*把completeData变成cover.ftl需要的格式*/
        LinkedList<CoverTable> tableData = changeDataToCoverTable(completeData);
        /*在res目录下创建cover.html*/
        makeCoverHtml(tableData, parentDirectoryPath(packagePath) + sp + "web" + sp + "res");
        HashMap<String, String> titleMap = addTileNumber(keyMap);


        keyMap.put("cover",parentDirectoryPath(packagePath) + sp + "web" + sp + "res"+sp+"cover.html");

        /*做文档结构html*/
        keyMap.putAll(stupid.makeDocumentHtml(packagePath));
        String acover2Px = keyMap.get("acover2Px");
        keyMap.remove("acover2Px");

        /*把里面路径变成相对路径*/
        keyMap = KeyMapToHtml(keyMap,packagePath);


        keyMap.put("acoverPx",coverPx(tableData));
        keyMap.put("acover2Px",acover2Px);
        keyMap.putAll(titleMap);
        /*终于到了最后一步，前面的步骤还要优化，唉..*/
        makeResultHtml(keyMap,packagePath);
    }

    private static HashMap<String, String> addTileNumber(HashMap<String, String> keyMap) {
        ArrayList<String> allLists = new ArrayList<>();
        HashMap<String, String> allMap = new HashMap<>();
        Set<String> strings2 = dataToHtml.getKey(new fly().getJarPath() + sp + "config" + sp + "keyValue.properties").keySet();
        for(String s: strings2){
            String s3 = s.substring(0, 3);
            s3 = "a" + s3.replace("_","");
            allMap.put(s3," ");
            if(!allLists.contains(s3)){
            allLists.add(s3);}
        }
        allMap.put("a51"," ");
        allLists.add("a51");
        allLists.sort(c2);
        for(String kk : keyMap.keySet()){
            String s3 = kk.substring(0, 3);
            s3 = "a" + s3.replace("_","");
            if(allMap.containsKey(s3)){
                allMap.put(s3,"t");
            }
        }
        allMap.put("a51","t");
        int t1 = 0;
        int t2 = 0;
        int t3 = 0;
        int t4 = 0;
        int t5 = 0;
        for (String s : allLists) {
            String ll = s.substring(1, 2);
            if (ll.equals("1") && allMap.get(s).equals("t")) {
                t1++;
                allMap.put(s,titleStr(t1));
            }
            if (ll.equals("2") && allMap.get(s).equals("t")) {
                t2++;
                allMap.put(s, titleStr(t2));
            }
            if (ll.equals("3") && allMap.get(s).equals("t")) {
                t3++;
                allMap.put(s, titleStr(t3));
            }
            if (ll.equals("4") && allMap.get(s).equals("t")) {
                t4++;
                allMap.put(s, titleStr(t4));
            }
            if (ll.equals("5") && allMap.get(s).equals("t")) {
                t5++;
                allMap.put(s, titleStr(t5));
            }
        }
        return allMap;
    }

    private static String titleStr(int t1) {
        if(t1 == 1){return "一 、 ";}
        if(t1 == 2){return "二 、 ";}
        if(t1 == 3){return "三 、 ";}
        if(t1 == 4){return "四 、 ";}
        if(t1 == 5){return "五 、 ";}
        if(t1 == 6){return "六 、 ";}
        if(t1 == 7){return "七 、 ";}
        if(t1 == 8){return "八 、 ";}
        if(t1 == 9){return "九 、 ";}
        return " ";
    }

    private static String coverPx(LinkedList<CoverTable> tableData) {
        int length = 0;
        for(CoverTable c:tableData){
            int rowspan = c.getFirstLine().getRowspan();
            length = length + rowspan;
        }
        int result = 45 + 45*length;
        return (result + "px");
    }

    private static void makeResultHtml(HashMap<String, String> keyMap, String packagePath) {
        String jarPath = new fly().getJarPath();
        String path = parentDirectoryPath(packagePath);

        try {
            Configuration configuration = new Configuration(Configuration.getVersion());
            configuration.setDirectoryForTemplateLoading(new File(jarPath + sp + "ftl"));
            configuration.setDefaultEncoding("UTF-8");
            Template template = configuration.getTemplate("results" + ".ftl");
            Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(path + sp + "results.html")), StandardCharsets.UTF_8));
            HashMap<String, Object> map = new HashMap<>(keyMap);
            template.process(map, writer);
            writer.close();
        } catch (IOException | TemplateException e) {
            e.printStackTrace();
        }

    }

    private static HashMap<String, String> KeyMapToHtml(HashMap<String, String> keyMap,String packagePath) {
        HashMap<String, String> result = new HashMap<>();
        packagePath = fly.parentDirectoryPath(packagePath);
        packagePath = makeSameTypePath(packagePath);
        for(String s : keyMap.keySet()){
            String s1 = keyMap.get(s);
            s1 = makeSameTypePath(s1);
            String[] split = s1.split(packagePath);
            String re = "." + split[1];
            s = s.replace("_","");
            s = "a" + s;
            result.put(s,re);
        }
        return result;
    }

    private static HashMap<String, tagTable> insertCompleteData(HashMap<String, tagTable> completeData, HashMap<String, String> keyMap) {
        HashMap<String, String> key = new HashMap<>();
        for (String k : keyMap.keySet()) {
            key.put(k.substring(0, 3), "");
        }
        Set<String> key2 = key.keySet();
        LinkedList<String> key3 = key2Sort(key2);
        return insertTagTable(completeData, key3);
    }

    private static HashMap<String, tagTable> insertTagTable(HashMap<String, tagTable> completeData, LinkedList<String> key3) {
        HashMap<String, tagTable> result = new HashMap<>();
        tagTable tt1 = new tagTable();
        tagTable tt2 = new tagTable();
        tagTable tt3 = new tagTable();
        tagTable tt4 = new tagTable();
        tagTable tt5 = new tagTable();
        for (String value : key3) {
            String[] s = value.split("_");
            String s1 = s[0];
            String s2 = s[1];
            tagTable tagTable = completeData.get(s1);
            if (s1.equals("1")) {
                tt1.setProject(tagTable.getProject());
                tt1.getContent().add(tagTable.getContent().get(Integer.parseInt(s2) - 1));
                tt1.getRequire().add(tagTable.getRequire().get(Integer.parseInt(s2) - 1));
                tt1.getDirectories().add(tagTable.getDirectories().get(Integer.parseInt(s2) - 1));
            }
            if (s1.equals("2")) {
                tt2.setProject(tagTable.getProject());
                tt2.getContent().add(tagTable.getContent().get(Integer.parseInt(s2) - 1));
                tt2.getRequire().add(tagTable.getRequire().get(Integer.parseInt(s2) - 1));
                tt2.getDirectories().add(tagTable.getDirectories().get(Integer.parseInt(s2) - 1));
            }
            if (s1.equals("3")) {
                tt3.setProject(tagTable.getProject());
                tt3.getContent().add(tagTable.getContent().get(Integer.parseInt(s2) - 1));
                tt3.getRequire().add(tagTable.getRequire().get(Integer.parseInt(s2) - 1));
                tt3.getDirectories().add(tagTable.getDirectories().get(Integer.parseInt(s2) - 1));
            }
            if (s1.equals("4")) {
                tt4.setProject(tagTable.getProject());
                tt4.getContent().add(tagTable.getContent().get(Integer.parseInt(s2) - 1));
                tt4.getRequire().add(tagTable.getRequire().get(Integer.parseInt(s2) - 1));
                tt4.getDirectories().add(tagTable.getDirectories().get(Integer.parseInt(s2) - 1));
            }
            if (s1.equals("5")) {

                tt5.setProject(tagTable.getProject());
                tt5.getContent().add(tagTable.getContent().get(Integer.parseInt(s2) - 1));
                tt5.getRequire().add(tagTable.getRequire().get(Integer.parseInt(s2) - 1));
                tt5.getDirectories().add(tagTable.getDirectories().get(Integer.parseInt(s2) - 1));
            }

        }
        if (tt1.getProject() != null) {
            tt1.setLength(tt1.getRequire().size());
            result.put("1", tt1);
        }
        if (tt2.getProject() != null) {
            tt2.setLength(tt2.getRequire().size());
            result.put("2", tt2);
        }
        if (tt3.getProject() != null) {
            tt3.setLength(tt3.getRequire().size());
            result.put("3", tt3);
        }
        if (tt4.getProject() != null) {
            tt4.setLength(tt4.getRequire().size());
            result.put("4", tt4);
        }
        if (tt5.getProject() != null) {
            tt5.setLength(tt5.getRequire().size());
            result.put("5", tt5);
        }
        return result;
    }

    private static LinkedList<String> key2Sort(Set<String> key2) {
        Object[] objects = key2.toArray();
        LinkedList<String> result = new LinkedList<>();
        for (Object object : objects) {
            result.add(object.toString());
        }
        result.add("5_1");
        result.sort(c);
        return result;
    }

    /*用cover.ftl模板导出cover.html到res目录下*/
    private static void makeCoverHtml(LinkedList<CoverTable> tableData, String s) {
        String jarPath = new fly().getJarPath();
        try {
            Configuration configuration = new Configuration(Configuration.getVersion());
            configuration.setDirectoryForTemplateLoading(new File(jarPath + sp + "ftl"));
            configuration.setDefaultEncoding("UTF-8");
            Template template = configuration.getTemplate("cover" + ".ftl");
            Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(s + sp + "cover.html")), StandardCharsets.UTF_8));
            HashMap<String, Object> map = new HashMap<>();
            map.put("coverTable", tableData);
            template.process(map, writer);
            writer.close();
        } catch (IOException | TemplateException e) {
            e.printStackTrace();
        }

    }

    /*创建了res目录顺便执行onlyCopyDirs*/
    private static void mkDirRes(String packagePath) {
        String resPath = packagePath + sp + "web" + sp + "res";
        File resFile = new File(resPath);
        if (!resFile.exists()) {
            boolean mkdirs = resFile.mkdirs();
            if(!mkdirs){System.out.println("error mkdirs res");}
        }
            String resultPath = packagePath + sp + "results";
            File resultFile = new File(resultPath);
            onlyCopyDirs(resultFile, resFile);

    }

    /*递归完成创建文件夹*/
    private static void onlyCopyDirs(File resultFile, File resFile) {
        File[] files = resultFile.listFiles();
        if (files != null) {
            for (File f : files) {
                if (f.isDirectory()) {
                    String name = f.getName();
                    String path = resFile.getAbsolutePath() + sp + name;
                    File file = new File(path);
                    if (!file.exists()) {
                        boolean mkdirs = file.mkdirs();
                        if(!mkdirs){System.out.println("error mkdirs res");}
                    }
                    onlyCopyDirs(f, file);
                }
            }
        }
    }

    /*把数据变成CoverTable集合，用于创建coverhtml*/
    private static LinkedList<CoverTable> changeDataToCoverTable(HashMap<String, tagTable> completeData) {
        LinkedList<CoverTable> result = new LinkedList<>();
        Set<String> keys = completeData.keySet();
        for (String k : keys) {
            tagTable tagTable = completeData.get(k);
            CoverTable coverTable = tagTable.toCoverTable();
            result.add(coverTable);
        }

        return result;
    }

    /*初始化完全的表格数据*/
    private static HashMap<String, tagTable> initCompleteData() {
        String tag1 = "OTU聚类与物种注释-" +
                "数据统计:OTU聚类:分类学分析-" +
                " : : -" +
                "Data/:OTU_Taxa/:OTU_Taxa/";
        String tag2 = "alpha多样性-" +
                "多样性指数:稀释曲线:shannon曲线:rank abundance:specaccum物种累积曲线-" +
                " : : :样本≥2:样本≥5-" +
                "Estimators/:Rarefaction/:Shannon_rarefac/:Rank_Abundance/:Specaccum/";
        String tag3 = "物种组成分析-" +
                "venn图(花瓣图):组分图:聚类树与组分图结合分析:heatmap图:core microbiome分析:优势物种群落结构组分图-" +
                "样本≥2:样本≥2:样本≥2:样本≥2:样本≥2:样本≥2-" +
                "Venn/:Community/:Hcluster_bar/:Heatmap/:Core/:Dominant_species/";
        String tag4 = "比较分析(beta多样性)-" +
                "组间距离分析:PCA分析:PCOA分析:基于UniFrac的PCOA分析:Nmds分析:多样本相似度树状图:基于Unifrac的聚树类分析:anosim:adonis-" +
                "分组≥2，每组样本≥3:样本≥3:样本≥3:样本≥3:样本≥3:样本≥3:样本≥3:分组≥2，每组样本≥3:分组≥2，每组样本≥3-" +
                "Distance/:PCA/:PCOA/:PCOA/:Numds/:Hcluster_tree/:Hcluster_tree/:Anosim/:Adonis/";
        String tag5 = "差异分析-" +
                "LEFSE分析:ANOVA方差分析:Wilcoxon秩和检验分析-" +
                "8≥分组≥2，每组样本≥3:分组≥2，每组样本≥3:分组=2，每组样本≥3-" +
                "Lefse/:Anova/:Wilcoxon/";
        HashMap<String, tagTable> result = new HashMap<>();
        result.put("1", new tagTable(tag1));
        result.put("2", new tagTable(tag2));
        result.put("3", new tagTable(tag3));
        result.put("4", new tagTable(tag4));
        result.put("5", new tagTable(tag5));
        return result;
    }


    /*copy基础web所需文件*/
    private static void copyWebBaseNeed(String packagePath) {
        String webParentPackagePath = parentDirectoryPath(packagePath);
        String jarWebPackagePath = new fly().getJarPath() + sp + "web";
        FileUtil.copyDir(jarWebPackagePath, webParentPackagePath);
    }

    /*获得上级目录*/
    public static String parentDirectoryPath(String packagePath) {
        return new File(packagePath).getParent();
    }

    /*获得脚本当前目录*/
    public String getJarPath() {
        String path = this.getClass().getProtectionDomain().getCodeSource().getLocation().getPath();
        if (System.getProperty("os.name").contains("dows")) {
            path = path.substring(1);
        }
        if (path.contains("jar")) {
            path = path.substring(0, path.lastIndexOf("."));
            return path.substring(0, path.lastIndexOf("/"));
        }
        return path.replace("target/classes/", "");
    }


    public static String makeSameTypePath(String path){
         path =  path.replace("\\", "/");
         path = path.replace(sp,"/");
         return path;
    }
}
